import { Context } from 'hono'
import { HTTPException } from 'hono/http-exception'
import { ZodError } from 'zod'
import { Prisma } from '@/lib/database'

// 自定义错误类
export class AppError extends Error {
  public statusCode: number
  public code: string
  public isOperational: boolean

  constructor(message: string, statusCode: number = 500, code: string = 'INTERNAL_ERROR') {
    super(message)
    this.statusCode = statusCode
    this.code = code
    this.isOperational = true

    Error.captureStackTrace(this, this.constructor)
  }
}

// 业务错误类
export class ValidationError extends AppError {
  public details?: any

  constructor(message: string, details?: any) {
    super(message, 400, 'VALIDATION_ERROR')
    this.details = details
  }
}

export class AuthenticationError extends AppError {
  constructor(message: string = 'Authentication required') {
    super(message, 401, 'AUTH_REQUIRED')
  }
}

export class AuthorizationError extends AppError {
  constructor(message: string = 'Permission denied') {
    super(message, 403, 'PERMISSION_DENIED')
  }
}

export class NotFoundError extends AppError {
  constructor(resource: string = 'Resource') {
    super(`${resource} not found`, 404, 'NOT_FOUND')
  }
}

export class ConflictError extends AppError {
  constructor(message: string) {
    super(message, 409, 'CONFLICT')
  }
}

export class RateLimitError extends AppError {
  constructor(message: string = 'Rate limit exceeded') {
    super(message, 429, 'RATE_LIMIT_EXCEEDED')
  }
}

// 错误响应格式
interface ErrorResponse {
  success: false
  error: {
    code: string
    message: string
    details?: any
    field?: string
    stack?: string
  }
  meta: {
    timestamp: string
    requestId: string
    path: string
  }
}

// 生成请求ID
const generateRequestId = (): string => {
  return Math.random().toString(36).substring(2, 15) +
    Math.random().toString(36).substring(2, 15)
}

// 错误处理中间件
export const errorHandler = async (err: Error, c: Context): Promise<Response> => {
  const requestId = generateRequestId()
  const timestamp = new Date().toISOString()
  const path = c.req.path

  // 记录错误日志
  console.error(`[${requestId}] Error occurred:`, {
    error: err.message,
    stack: err.stack,
    path,
    method: c.req.method,
    timestamp
  })

  let statusCode = 500
  let errorCode = 'INTERNAL_ERROR'
  let message = 'Internal server error'
  let details: any = undefined

  // 处理不同类型的错误
  if (err instanceof AppError) {
    // 自定义应用错误
    statusCode = err.statusCode
    errorCode = err.code
    message = err.message
    if (err instanceof ValidationError) {
      details = err.details
    }
  } else if (err instanceof HTTPException) {
    // Hono HTTP 异常
    statusCode = err.status
    errorCode = `HTTP_${err.status}`
    message = err.message
  } else if (err instanceof ZodError) {
    // Zod 验证错误
    statusCode = 400
    errorCode = 'VALIDATION_ERROR'
    message = 'Validation failed'
    details = err.errors.map(error => ({
      field: error.path.join('.'),
      message: error.message,
      code: error.code
    }))
  } else if (err instanceof Prisma.PrismaClientKnownRequestError) {
    // Prisma 数据库错误
    statusCode = 400
    errorCode = 'DATABASE_ERROR'

    switch (err.code) {
      case 'P2002':
        message = 'Unique constraint violation'
        details = { field: err.meta?.target }
        break
      case 'P2025':
        statusCode = 404
        errorCode = 'NOT_FOUND'
        message = 'Record not found'
        break
      case 'P2003':
        message = 'Foreign key constraint violation'
        break
      case 'P2014':
        message = 'Invalid ID provided'
        break
      default:
        message = 'Database operation failed'
        break
    }
  } else if (err instanceof Prisma.PrismaClientValidationError) {
    // Prisma 验证错误
    statusCode = 400
    errorCode = 'VALIDATION_ERROR'
    message = 'Invalid data provided'
  } else if (err instanceof Prisma.PrismaClientInitializationError) {
    // Prisma 初始化错误
    statusCode = 503
    errorCode = 'SERVICE_UNAVAILABLE'
    message = 'Database connection failed'
  } else if (err.name === 'JsonWebTokenError') {
    // JWT 错误
    statusCode = 401
    errorCode = 'AUTH_INVALID'
    message = 'Invalid authentication token'
  } else if (err.name === 'TokenExpiredError') {
    // JWT 过期错误
    statusCode = 401
    errorCode = 'AUTH_EXPIRED'
    message = 'Authentication token expired'
  } else if (err.name === 'MulterError') {
    // 文件上传错误
    statusCode = 400
    errorCode = 'FILE_UPLOAD_ERROR'
    message = err.message
  }

  // 构建错误响应
  const errorResponse: ErrorResponse = {
    success: false,
    error: {
      code: errorCode,
      message,
      ...(details && { details }),
      ...(c.env?.NODE_ENV === 'development' && { stack: err.stack })
    },
    meta: {
      timestamp,
      requestId,
      path
    }
  }

  // 设置响应头
  c.header('X-Request-ID', requestId)
  c.header('Content-Type', 'application/json')

  return c.json(errorResponse, statusCode as any)
}

// 异步错误包装器
export const asyncHandler = (fn: (c: Context, next?: Function) => Promise<any>) => {
  return (c: Context, next?: Function) => {
    return Promise.resolve(fn(c, next)).catch((err) => {
      throw err
    })
  }
}

// 404 错误处理
export const notFoundHandler = () => {
  throw new NotFoundError('Endpoint')
}
